package main

import (
	"context"
	"gitee.com/zaiqiang231/go-base-app/base_app"
	baseConfig "gitee.com/zaiqiang231/go-base-app/base_app/config"
	baseHttp "gitee.com/zaiqiang231/go-base-app/base_app/http"
	baseLog "gitee.com/zaiqiang231/go-base-app/base_app/log"
	baseRpc "gitee.com/zaiqiang231/go-base-app/base_app/rpc"
	"gitee.com/zaiqiang231/go-base-app/base_app/store"
	"gitee.com/zaiqiang231/go-base-app/base_app/task"
	"gitee.com/zaiqiang231/go-base-app/base_app/tracer"
	"gitee.com/zaiqiang231/go-base-app/example/model"
	"github.com/fatih/color"
	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
	"golang.org/x/sync/errgroup"
	"gorm.io/gorm"
	"net/http"
)

func main() {
	base_app.NewApp(
		"test-service", // 服务名， 没有设置配置文件路径时，默认寻找 工作目录下的 [basename] 配置文件
		initConfig,
		base_app.WithCmdDescription("example server desc"),
		base_app.WithRunFunc(run),
	).Run()
}

var GlobalAppConfig = new(baseConfig.AppConfig)

func initConfig(a *base_app.App) {
	baseLog.Debugf("开始读取配置")
	if err := viper.Unmarshal(GlobalAppConfig); err != nil {
		baseLog.Fatalf("读取配置失败: %v", err)
	}
	baseLog.Debugf("读取配置: GlobalConfig = %v", GlobalAppConfig)

	var err error
	//初始化mysql
	_, err = store.InitDataStore(GlobalAppConfig.MysqlConfig)
	if err != nil {
		baseLog.Errorf("failed to initStore : %v", err)
	}
	InitDb()

	//初始化redis
	_, err = store.InitRedisStore(GlobalAppConfig.RedisConfig)
	if err != nil {
		baseLog.Errorf("failed to initStore : %v", err)
	}

	//初始化remote rpc
	//_, err = remoteRpc.InitTestRpc("127.0.0.1:6002")
	//if err != nil {
	//	baseLog.Errorf("failed to init session rpc : %v", err)
	//}

	//初始化 链路追踪
	tracer.InitTracer(GlobalAppConfig.TracerConfig.Url, "test-service", "127.0.0.1:80")
}

// 配置已经读取完成后，再启动服务
func run(basename string) error {
	baseLog.Infof("%v %v 应用启动", color.GreenString("LoveSport:"), basename)
	defer func() {
		baseLog.Infof("%v %v 应用退出", color.GreenString("LoveSport:"), basename)
	}()

	var eg errgroup.Group
	gs := base_app.NewGracefulShutdown()
	//http 服务
	base_app.CreateAPIServer(
		basename,
		base_app.WithServerConfig(GlobalAppConfig.ServerConfig),
		base_app.WithGracefulShutdown(gs),
		base_app.WithRouter(InitRouter),
	).PrepareRun().Run(&eg)

	//rpc 服务
	baseRpc.CreateGrpcServer(basename+" rpc",
		baseRpc.WithAddress(GlobalAppConfig.GRpcServerConfig.Addr),
		baseRpc.WithGracefulShutdown(gs),
		baseRpc.WithGRpcServer(InitGRpc),
	).PrepareRun().Run(&eg)

	//定时任务
	task.GetTimedTaskManager().Start()

	//优雅关闭监听启动
	if err := gs.Start(); err != nil {
		baseLog.Fatalf("%v start shutdown manager failed: %s", basename, err.Error())
	}

	if err := eg.Wait(); err != nil {
		baseLog.Fatalf("ApiServer eg.Wait() err: ", err.Error())
	}

	return nil
}

func InitRouter(g *gin.Engine) {
	g.Use(gin.Logger(), gin.Recovery())

	user := g.Group("/test")
	{
		user.GET("/getModel", getModel) //获取验证码
	}
}

func getModel(c *gin.Context) {
	spanP, ctx := tracer.GetTracer().StartSpanFromContext(c, "request-sayHi-P")
	defer spanP.Finish()
	getModelChild(ctx, c)
}

func getModelChild(ctx context.Context, c *gin.Context) {
	spanC, _ := tracer.GetTracer().StartSpanFromContext(ctx, "request-sayHi-C")
	defer spanC.Finish()

	var request model.TestModelReq
	if err := c.ShouldBindQuery(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), gin.H{
			"traceId": spanC.Context().TraceID,
		})
		return
	}

	var target = model.TestModel{}
	var err error
	store.GetDataStore().Execute(func(db *gorm.DB) {
		err = db.Transaction(func(tx *gorm.DB) error {
			return tx.Model(&model.TestModel{}).Where("name = ?", request.Name).First(&target).Error
		})
	})

	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), gin.H{
			"traceId": spanC.Context().TraceID,
		})
		return
	}

	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"traceId": spanC.Context().TraceID,
		"data":    target,
	})
}
